Skip to main content

10-Minute Tutorial

Creating an Empty Cucumber Project

Start by creating an empty Node.js project.

mkdir hellocucumber
cd hellocucumber
npm init --yes

Install Cucumber as a dev dependency:

npm install --save-dev @cucumber/cucumber

Add the test command to package.json:

{
"name": "hellocucumber",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "cucumber-js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@cucumber/cucumber": "^11.1.1"
}
}

Prepare the file structure:

mkdir features
mkdir features/step_definitions

Create a file called cucumber.json at the root of the project. Add the following:

{
"default": {
"formatOptions": {
"snippetInterface": "synchronous"
}
}
}

Create a file called features/step_definitions/stepdefs.js with the following content:

const assert = require('assert');
const { Given, When, Then } = require('@cucumber/cucumber');

Verify your Installation

To make sure everything is working properly, run the tests.

npm test

You should see the following output:

0 scenarios
0 steps
0m00.000s

Write a Scenario

BDD is done in Cucumber with concrete examples that specify what we want the software to do. These scenarios are written before production code. The start of their life is called an executable specification. As production code is written, scenarios take the role as living documentation and automated tests.

Any example is called a scenario. Scenarios are defined in .feature files, which are stored in the features directory (or sub-directory)

Here is an example that Sunday isn't Friday

Create a file called features/is_it_friday_yet.feature

Feature: Is it Friday yet?
Everybody wants to know when it's Friday

Scenario: Sunday isn't Friday
Given today is Sunday
When I ask whether it's Friday yet
Then I should be told "Nope"

The lines...

  • First Line: The name of the Scenario (Should be similar to the file name)
  • Second Line: The description of the scenario.
  • Fourth Line: The Scenario.
  • Remaining Lines: These are the steps of the scenario, which will be executed by Cucumber.

Ask cucumber to execute the scenario:

npm test

Cucumber will let you know that there is one undefined scenario and three undefined steps. It will also suggest snippets to define these steps:

UUU

Warnings:

1) Scenario: Sunday is not Friday # features/is_it_friday_yet.feature:4
? Given today is Sunday
Undefined. Implement with the following snippet:

Given('today is Sunday', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});

? When I ask whether it's Friday yet
Undefined. Implement with the following snippet:

When('I ask whether it\'s Friday yet', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});

? Then I should be told "Nope"
Undefined. Implement with the following snippet:

Then('I should be told {string}', function (string) {
// Write code here that turns the phrase above into concrete actions
return 'pending';
});


1 scenario (1 undefined)
3 steps (3 undefined)
0m00.000s

For now, copy each of thes three snupped and paste them into `features/step_definitions/stepdefs.js

See Scenario reported as pending

Running cucumber again:

P--

Warnings:

1) Scenario: Sunday is not Friday # features/is_it_friday_yet.feature:4
? Given today is Sunday # features/step_definitions/stepdefs.js:3
Pending
- When I ask whether it's Friday yet # features/step_definitions/stepdefs.js:8
- Then I should be told "Nope" # features/step_definitions/stepdefs.js:13

1 Scenario (1 pending)
3 steps (1 pending, 2 skipped)
0m00.001s

Being marked as pending means they need to do something useful.

See scenario reported as failing

Then, do what the comments in each step definition is telling us to do.

Change the step definitions to this:

const assert = require('assert');
const { Given, When, Then } = require('@cucumber/cucumber');

function isItFriday(today) {
// We'll leave the implementation blank for now
}

Given('today is Sunday', function () {
this.today = 'Sunday';
});

When('I ask whether it\'s Friday yet', function () {
this.actualAnswer = isItFriday(this.today);
});

Then('I should be told {string}', function (expectedAnswer) {
assert.strictEqual(this.actualAnswer, expectedAnswer);
});

Then run cucumber again

..F

Failures:

1) Scenario: Sunday is not Friday # features/is_it_friday_yet.feature:4
✔ Given today is Sunday # features/step_definitions/stepdefs.js:8
✔ When I ask whether it's Friday yet # features/step_definitions/stepdefs.js:12
✖ Then I should be told "Nope" # features/step_definitions/stepdefs.js:16
AssertionError [ERR_ASSERTION]: undefined == 'Nope'
at World.<anonymous> (/private/tmp/tutorial/hellocucumber/features/step_definitions/stepdefs.js:17:10)

1 Scenario (1 failed)
3 steps (1 failed, 2 passed)

Two tests should be passing, but the last one will fail.

See scenario reported as passing

Do the bare minimum t make the scenario pass

function isItFriday(today) {
return 'Nope';
}

Running cucumber again:

...

1 scenario (1 passed)
3 steps (3 passed)
0m00.003s

Add another failing test

The next thing to do would be to get the correct return when it is Friday. Update the is_it_friday_yet.feature

Feature: Is it Friday yet?
Everybody wants to know when it's Friday

Scenario: Sunday isn't Friday
Given today is Sunday
When I ask whether it's Friday yet
Then I should be told "Nope"

Scenario: Friday is Friday
Given today is Friday
When I ask whether it's Friday yet
Then I should be told "TGIF"

Add a step definition to set today to Friday

Given("today is Friday", function () {
this.today = "Friday";
});

Running the test will cause it to fail:

.....F

Failures:

1) Scenario: Friday is Friday # features/is_it_friday_yet.feature:9
✔ Given today is Friday # features/step_definitions/stepdefs.js:8
✔ When I ask whether it's Friday yet # features/step_definitions/stepdefs.js:16
✖ Then I should be told "TGIF" # features/step_definitions/stepdefs.js:20
AssertionError [ERR_ASSERTION]: 'Nope' == 'TGIF'
+ expected - actual

-Nope
+TGIF

at World.<anonymous> (/private/tmp/tutorial/hellocucumber/features/step_definitions/stepdefs.js:21:10)

2 scenarios (1 failed, 1 passed)
6 steps (1 failed, 5 passed)

Make it Pass

Update the statement to actually evaluate if today is Friday.

function isItFriday(today) {
if (today === "Friday") {
return "TGIF";
} else {
return "Nope";
}
}

Running the test suite:

......
2 scenarios (2 passed)
6 steps (6 passed)
0m00.002s

Using variables and examples

Update the scenario to use variables and evaluate numerous possibilities. Update the is_it_friday_yet.feature file. Note the difference between Scenario and Scenario Outline

Feature: Is it Friday yet?
Everybody wants to know when it's Friday

Scenario Outline: Today is or is not Friday
Given today is "<day>"
When I ask whether it's Friday yet
Then I should be told "<answer>"

Examples:
| day | answer |
| Friday | TGIF |
| Sunday | Nope |
| anything else! | Nope |

Replace the step definitions for today is Sunday and today is Friday with one step definition that takes the value of day as a string.

const assert = require('assert');
const { Given, When, Then } = require('@cucumber/cucumber');

function isItFriday(today) {
if (today === "Friday") {
return "TGIF";
} else {
return "Nope";
}
}

Given('today is {string}', function (givenDay) {
this.today = givenDay;
});

When('I ask whether it\'s Friday yet', function () {
this.actualAnswer = isItFriday(this.today);
});

Then('I should be told {string}', function (expectedAnswer) {
assert.strictEqual(this.actualAnswer, expectedAnswer);
});

Running cucumber again:

.........

3 scenarios (3 passed)
9 steps (9 passed)
0m00.001s